package com.ajavaer.framework.shiro;

import com.ajavaer.framework.AjavaerCache;
import com.ajavaer.framework.cache.CommonCache;
import com.ajavaer.framework.cache.DefaultCache;
import com.ajavaer.framework.cache.RedisCache;
import com.ajavaer.framework.common.tools.StringTools;
import com.ajavaer.framework.config.ShiroConfig;
import com.ajavaer.framework.handle.CacheHandle;
import com.ajavaer.framework.handle.RedisHandle;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.apache.shiro.cache.CacheManager;

import java.util.concurrent.ConcurrentHashMap;

public class ShiroCacheManager implements CacheManager {

    private ShiroConfig shiroConfig;

    public void init(ShiroConfig shiroConfig) {
        this.shiroConfig = shiroConfig;
    }

    private ConcurrentHashMap cache = new ConcurrentHashMap();

    @Override
    public <K, V> Cache<K, V> getCache(String name) throws CacheException {
        if (StringTools.isBlank(name)) {
            return null;
        }
        Cache cache = (Cache) this.cache.get(name);
        if (cache == null) {
            if (shiroConfig.getCacheEngine() != null) {
                if (AjavaerCache.has(shiroConfig.getCacheEngine())) {
                    CacheHandle<K, V> cacheHandle = AjavaerCache.get(shiroConfig.getCacheEngine());
                    if (cacheHandle != null) {
                        switch (shiroConfig.getCacheEngine()) {
                            case redis:
                                cache = new RedisCache<>((RedisHandle) cacheHandle, shiroConfig.getCachePrefix());
                                break;
                            default:
                                cache = new CommonCache(cacheHandle);

                        }
                    }
                } else {
                    throw new CacheException("CacheEngine " + shiroConfig.getCacheEngine() + " has not been defined");
                }
            } else {
                cache = new DefaultCache();
            }
            this.cache.put(name, cache);
        }

        return cache;
    }
}
